package com.example.demo.utils;

import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.pdf.PdfExportUtil;
import cn.afterturn.easypoi.pdf.entity.PdfExportParams;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * PDF数据导出
 *
 * @author Liunh
 */
@Slf4j
public class PdfUtil {

    private static volatile PdfUtil instance = null;
    private final Font titleFont = FontFactory.getFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED, 15f, Font.BOLD, BaseColor.BLACK);
    private final Font headerFont = FontFactory.getFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED, 11f, Font.BOLD, BaseColor.BLACK);
    private final Font contentFont = FontFactory.getFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED, 10f);

    private PdfUtil() {
    }

    public static PdfUtil getInstance() {
        if (null == instance) {
            synchronized (PdfUtil.class) {
                if (null == instance) {
                    instance = new PdfUtil();
                }
            }
        }
        return instance;
    }

    public String fileName(String title) {
        String filesSavePath = FileUtil.getInstance().fileSavePath();
        return StringUtils.isBlank(title) ? filesSavePath + "export_data_" + System.currentTimeMillis() + ".pdf" : filesSavePath + title + "_" + System.currentTimeMillis() + ".pdf";
    }


    public String exportPdf(String title, final List<ExcelExportEntity> entityList, final List<LinkedHashMap<String, Object>> dataList) {
        return exportPdf(title, null, entityList, dataList);
    }

    public String exportPdf(String title, PdfExportParams entity, final List<ExcelExportEntity> entityList, final List<LinkedHashMap<String, Object>> dataList) {
        PDDocument document = null;
        String fileName = null;
        try {
            fileName = this.fileName(title);
            entity = entity == null ? new PdfExportParams(StringUtils.isBlank(title) ? "export_data" : title) : entity;
            document = PdfExportUtil.exportPdf(entity, entityList, dataList);
            document.save(fileName);
            log.info(">>>>>> Export PDF completed. file name = {}", fileName);
        } catch (Exception e) {
            log.error(">>>>>> Export PDF Exception. fileName = {}", fileName, e);
        } finally {
            if (document != null) {
                try {
                    document.close();
                } catch (Exception e) {
                    log.error(">>>>>> Export PDF close document Exception. fileName = {}", fileName, e);
                }
            }
        }
        return fileName;
    }


    /**
     * PDF数据导出
     *
     * @param title       文件名
     * @param tableHeader 表头
     * @param dataList    表数据
     * @return 生成的文件路径
     */
    public String exportPdf(String title, final String[] tableHeader, final List<LinkedHashMap<String, Object>> dataList) {
        return this.exportPdf(title, null, null, tableHeader, null, dataList);
    }

    /**
     * PDF数据导出
     *
     * @param title       文件名
     * @param tableHeader 表头
     * @param tableWidths 表列宽
     * @param dataList    表数据
     * @return 生成的文件路径
     */
    public String exportPdf(String title, final String[] tableHeader, int[] tableWidths, final List<LinkedHashMap<String, Object>> dataList) {
        return this.exportPdf(title, null, null, tableHeader, tableWidths, dataList);
    }

    /**
     * PDF数据导出
     *
     * @param title       文件名
     * @param author      作者
     * @param creator     创建人
     * @param tableHeader 表头
     * @param tableWidths 表列宽
     * @param dataList    表数据
     * @return 生成的文件路径
     */
    public String exportPdf(String title, final String author, final String creator, final String[] tableHeader, final int[] tableWidths, final List<LinkedHashMap<String, Object>> dataList) {
        Document document = new Document();
        PdfWriter writer = null;
        String fileName = this.fileName(title);
        try {
            writer = PdfWriter.getInstance(document, new FileOutputStream(fileName));
            document.open();
            document.addTitle(title);
            if (StringUtils.isNotBlank(author)) {
                document.addAuthor(author);
            }
            if (StringUtils.isNotBlank(creator)) {
                document.addCreator(creator);
            }
            document.addCreationDate();
            document.add(this.fileTitle(title));
            document.add(this.emptyLine());

            int numColumns = tableHeader != null && tableHeader.length > 0 ? tableHeader.length : 1;
            PdfPTable table = new PdfPTable(numColumns);
            if (tableWidths != null && tableWidths.length > 0) {
                table.setWidths(tableWidths);
            }
            PdfPCell cell;
            if (tableHeader != null && tableHeader.length > 0) {
                for (String headerTile : tableHeader) {
                    cell = new PdfPCell(new Phrase(headerTile, headerFont));
                    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell.setFixedHeight(16);
                    table.addCell(cell);
                }
            }
            if (dataList != null && dataList.size() > 0) {
                for (LinkedHashMap<String, Object> map : dataList) {
                    if (map != null && map.size() > 0) {
                        for (Map.Entry<String, Object> entry : map.entrySet()) {
                            Object objVal = entry.getValue();
                            String cellValue = " ";
                            if (objVal != null) {
                                cellValue = String.valueOf(objVal);
                            }
                            cell = new PdfPCell(new Phrase(cellValue, contentFont));
                            cell.setFixedHeight(15);
                            table.addCell(cell);
                        }
                    }
                }
            }
            document.add(table);
            log.info(">>>>>> Export PDF completed. file name = {}", fileName);
        } catch (IOException | DocumentException e) {
            log.error(">>>>>> Export PDF Exception. fileName = {}", fileName, e);
        } finally {
            document.close();
            if (writer != null) {
                writer.close();
            }
        }
        return fileName;
    }

    /**
     * 文档顶部标题
     * document.add(this.fileTitle(title));
     *
     * @return
     */
    private Paragraph fileTitle(String title) {
        Paragraph paragraph = new Paragraph(title, titleFont);
        paragraph.setAlignment(Element.ALIGN_CENTER);
        return paragraph;
    }

    /**
     * 空白行
     * document.add(this.emptyLine());
     *
     * @return
     */
    private Paragraph emptyLine() {
        return new Paragraph("\n", contentFont);
    }

}
